package com.tgjorgoski.spellcheck;

import java.awt.*;
import java.awt.event.*;
import java.util.List;

import javax.swing.*;
import javax.swing.text.*;

import org.apache.log4j.Logger;

import com.swabunga.spell.engine.Word;
import com.tgjorgoski.sidekicknotes.rtfview.support.PopupMenuFiller;
import com.tgjorgoski.utils.IconResource;

/**
 * Gives spellcheck suggestions for the word where right click happened
 * 
 * @author Tanasije Gjorgoski <tgjorgoski@novizio.com>
 */
public class SpellcheckMenuFiller implements PopupMenuFiller {
	
	private static Logger log = Logger.getLogger(SpellcheckMenuFiller.class);

    /**
	 * @param populateThisMenu
	 * @param mw
	 * @param e
	 * 
	 * @see europa.client.sdoc.view.editorsEnrich.PopupMenuFiller#populateMenu(javax.swing.JPopupMenu,
	 *      europa.client.sdoc.model.ModelWrapper, java.awt.event.MouseEvent)
	 */
	public void populateMenu(JPopupMenu popup, MouseEvent e) {
		Object comp = e.getSource();
		if (!(comp instanceof JTextComponent)) return;
		JTextComponent editor = (JTextComponent)comp;
		if (editor.isEditable()) {
			Point pt = new Point(e.getX(), e.getY());
			int pos = editor.viewToModel(pt);
			if (pos >= 0) {
				Document hdoc = editor.getDocument();
				char ch;
				int start=0, end=0;
				try {
					//find the begining of the word
					for(start=pos; start>=0; start--) {
						ch = hdoc.getText(start, 1).charAt(0);
						if (!Character.isLetterOrDigit(ch)) {
							break;
						}
					}
					start++;
					//find the end
					int length= hdoc.getLength();
					for(end=pos; end<=length; end++) {
						ch = hdoc.getText(end, 1).charAt(0);
						if (!Character.isLetterOrDigit(ch)) {
							break;
						}
					}
					end--;
				} catch (BadLocationException exc) {
					exc.printStackTrace();
					return;
				}
				boolean selectionPresent=false;
				//we won't give suggestions if there is selction, and that selection is not the word
				//that is clicked
				if (editor.getSelectionStart()!=editor.getSelectionEnd()) selectionPresent=true;
				if (selectionPresent && (editor.getSelectionStart()!=start || editor.getSelectionEnd()!=end+1)) return;
				
				if (start<=end) {
					try {
						final String word = hdoc.getText(start, end-start+1);
						if (SpellcheckDictionaries.isCorrect(word)) return;
						List list = SpellcheckDictionaries.getSuggestions(word,5);
						//List list = dictionary.getSuggestions(word, 5);
						int index = 0;
						ReplaceTextListener listener = new ReplaceTextListener(start, end, hdoc, word);
						while (index < list.size() && index < 5) {
							Word w = (Word) list.get(index);
							JMenuItem item = new JMenuItem(w.getWord());
							item.setFont(item.getFont().deriveFont(Font.BOLD));
							item.setActionCommand(w.getWord());
							item.addActionListener(listener);
							popup.add(item);
							index++;
						}
						if (list.size()!=0)
							popup.addSeparator();
						JMenuItem item2 = new JMenuItem("Ignore All");
						item2.addActionListener(new ActionListener() {
							public void actionPerformed(ActionEvent e) {
								SpellcheckDictionaries.ignoreWord(word);
							}
						});
						popup.add(item2);
						JMenuItem item = new JMenuItem("Add to dictionary");
						//item.setIcon(IconResource.getIconResource("addword"));
						item.addActionListener(new ActionListener() {
							public void actionPerformed(ActionEvent e) {
								SpellcheckDictionaries.addWord(word);
							}
						});
						popup.add(item);
					} catch (BadLocationException f) {
						log.error(" Bad location:" + start + " count " + end, f);
					}
				}
			}
		}
	}
	
	class ReplaceTextListener implements ActionListener {
		int start;
		int end;
		Document doc;
		String word;
		
		public ReplaceTextListener(int start, int end, Document doc, String word) {
			this.start=start;
			this.end=end;
			this.doc = doc;
			this.word=word;
		}
		
		public void actionPerformed(ActionEvent e) {
			try {
				AttributeSet attSet=null;
				if (doc instanceof DefaultStyledDocument) {
					attSet = ((DefaultStyledDocument)doc).getCharacterElement(start).getAttributes();
				}
				doc.remove(start, end-start+1);
				//fix the capitalization
				String currentWord = word;
				String newWord =  e.getActionCommand();
				boolean upperCurrent=Character.isUpperCase(currentWord.charAt(0));
				boolean upperNew = Character.isUpperCase(newWord.charAt(0));
				if (upperCurrent!=upperNew) {
					StringBuffer capitalized = new StringBuffer();
					char firstChar = newWord.charAt(0);
					if (upperCurrent)
						firstChar = Character.toUpperCase(firstChar);
					else
						firstChar = Character.toLowerCase(firstChar);
					capitalized.append(firstChar);
					capitalized.append(newWord.substring(1));
					newWord=capitalized.toString();
				}
				
				doc.insertString(start, newWord, attSet);
			} catch (BadLocationException exc) {
				exc.printStackTrace();
			}
		}
	}
}